package cn.iocoder.yudao.module.wms.service.stock;

import cn.iocoder.yudao.module.wms.controller.admin.saleorder.vo.SaleDetialRespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.saleorder.SaleDetailDO;
import cn.iocoder.yudao.module.wms.service.saleorder.SaleOrderService;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.iocoder.yudao.module.wms.controller.admin.stock.vo.*;
import cn.iocoder.yudao.module.wms.dal.dataobject.stock.StockDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.stock.StockLogDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.wms.dal.mysql.stock.StockMapper;
import cn.iocoder.yudao.module.wms.dal.mysql.stock.StockLogMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.*;

/**
 * 存货管理 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class StockServiceImpl implements StockService {

    @Resource
    private StockMapper stockMapper;
    @Resource
    private StockLogMapper stockLogMapper;

    @Resource
    private SaleOrderService saleOrderService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createStock(StockSaveReqVO createReqVO) {
        // 插入
        StockDO stock = BeanUtils.toBean(createReqVO, StockDO.class);
        stockMapper.insert(stock);
        if (createReqVO.getStockLogs()!=null)
        {
            // 插入子表
            createStockLogList(stock.getId(), createReqVO.getStockLogs());
        }

        // 返回
        return stock.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStock(StockSaveReqVO updateReqVO) {
        // 校验存在
        validateStockExists(updateReqVO.getId());
        // 更新
        StockDO updateObj = BeanUtils.toBean(updateReqVO, StockDO.class);
        stockMapper.updateById(updateObj);

        // 更新子表
        updateStockLogList(updateReqVO.getId(), updateReqVO.getStockLogs());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteStock(Integer id) {
        // 校验存在
        validateStockExists(id);
        // 删除
        stockMapper.deleteById(id);

        // 删除子表
        deleteStockLogByInventoryId(id);
    }

    private void validateStockExists(Integer id) {
        if (stockMapper.selectById(id) == null) {
            throw exception(STOCK_NOT_EXISTS);
        }
    }

    @Override
    public StockRespVO getStock(Integer id) {
        return stockMapper.getStock(id);
    }

    @Override
    public PageResult<StockDO> getStockPage(StockPageReqVO pageReqVO) {
        return stockMapper.selectPage(pageReqVO);
    }

    // ==================== 子表（存货管理子） ====================

    @Override
    public List<StockLogDO> getStockLogListByInventoryId(StockLogDO stockLogDO) {
        return stockMapper.selectListByInventoryId(stockLogDO);
    }

    /***
     * 入库操作
     * @param
     */
    @Override
    public void store(StockDO stockDO) {
        try {

            stockMapper.insert(stockDO);

            //将日志记录
        }catch (Exception e)
        {
            throw exception(STOCK_NOT_FIND);
        }
    }


    /***
     * 出库操作
     * @param stockDO 必须是从zjjs_stock获取的 要有ID
     */
    @Override
    public void Outbound(StockDO stockDO) {
        try {

            StockDO s=stockMapper.findByInventoryId(stockDO);
            s.setQty(s.getQty()-stockDO.getQty());
            if (s.getQty()<0)
            {
                throw exception(STOCK_NOT_OUT);
            }
            stockMapper.updateById(s);
        }catch (Exception e)
        {
            throw exception(STOCK_NOT_FIND);
        }

    }

    /***
     * 删除库存
     * @param stockDO
     */
    @Override
    public void restore(StockDO stockDO) {
        //删除库存
        stockMapper.deleteByStock(stockDO);
    }


    /***
     * 删除库存
     * @param stockDO 需要数量
     */
    @Override
    public void restoreRK(StockDO stockDO) {
        //查询现有库存数量
        StockDO nowStockDo=stockMapper.findByInventoryId(stockDO);

        stockDO.setQty(stockDO.getQty()+nowStockDo.getQty());
        //恢复库存数量
        stockMapper.restoreByStock(stockDO);
    }


    /***
     * 调拨方法，修改仓库和货位
     * @param id
     * @return
     */
    public void allot()
    {


    }
    @Override
    public StockLogDO getStockLog(Integer id) {
        return stockLogMapper.selectById(id);
    }


    /***
     * 首先 查询销售订单的子表信息获取到需要的存货档案ID
     * 然后 通过存货档案ID和仓库ID去查询库存里可以出库的存货
     */
    @Override
    public List<StockRespVO> findAboutSaleStockLog(StockSaleSelectVO stockSaleSelectVO) {
        List<SaleDetialRespVO> saleDetialRespVOList=saleOrderService.findSaleDetialOperateList(stockSaleSelectVO.getSaleOrderId());
        List<StockRespVO> stockRespVOList=new ArrayList<>();
        for (SaleDetialRespVO s:saleDetialRespVOList)
        {
            stockSaleSelectVO.setInventoryId(s.getInventoryId());
            stockRespVOList.addAll(stockMapper.findSaleListByInventoryId(stockSaleSelectVO));
        }
        return stockRespVOList;
    }

    @Override
    public StockLogRespVO findStockLogById(Integer id) {
        return stockMapper.findStockLogById(id);
    }

    @Override
    public void updateStockLog(StockLogRespVO stockLogRespVO) {
        stockMapper.updateStockLog(stockLogRespVO);
    }

    @Override
    public int findBatchCodeDuplicate(String batchCode) {
        return stockMapper.findBatchCodeDuplicate(batchCode);
    }

    @Override
    public List<StockRespVO> findUseListByParam(StockSaleSelectVO stockSaleSelectVO) {
        return stockMapper.findSaleListByInventoryId(stockSaleSelectVO);
    }

    @Override
    public List<StockRespVO> viewStock(StockRespVO stockRespVO) {
        return stockMapper.viewStock(stockRespVO);
    }


    @Override
    public List<StockLogRespVO> findUsedAll() {
        return stockMapper.findUsedAll();
    }



    private void createStockLogList(Integer inventoryId, List<StockLogDO> list) {
        list.forEach(o -> o.setInventoryId(inventoryId));
        stockLogMapper.insertBatch(list);
    }

    private void updateStockLogList(Integer inventoryId, List<StockLogDO> list) {
        deleteStockLogByInventoryId(inventoryId);
		list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下：1）id 冲突；2）updateTime 不更新
        createStockLogList(inventoryId, list);
    }

    private void deleteStockLogByInventoryId(Integer inventoryId) {
        stockLogMapper.deleteByInventoryId(inventoryId);
    }

}